import tornado
import time
import logging
import json

from urllib.parse import urlencode

from extends.torndsession.sessionhandler import SessionBaseHandler
from util.flash import flash
from util.function import date_format, time_format
from util.function import not_need_login, humantime

from tornado.web import RequestHandler
from tornado.gen import coroutine
from tornado.web import asynchronous


class BaseHandler(SessionBaseHandler):

    def initialize(self):
        self.db = self.settings["database"]
        self.backend = self.settings["thread_pool"]
        self.flash = flash(self)
        self.results = dict()

    def prepare(self):
        self.add_header("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-eval'; "
                        "connect-src 'self'; img-src 'self' data:; style-src 'self'; "
                        "font-src 'self'; frame-src 'self'; ")
        self.add_header("X-Frame-Options", "deny")
        self.add_header("X-XSS-Protection", "1; mode=block")
        self.add_header("X-Content-Type-Options", "nosniff")
        self.add_header("x-ua-compatible:", "IE=edge,chrome=1")
        self.clear_header("Server")

    def redirect(self, url, permanent=False, status=None):
        super(BaseHandler, self).redirect(url, permanent, status)
        raise tornado.web.Finish()

    def render(self, template_name, **kwargs):
        kwargs.update({
            "date_format": date_format,
            "time_format": time_format,
            "humantime": humantime,
            'results': self.results,
            'pagenav': self.pagenav
        })
        super(BaseHandler, self).render(template_name, **kwargs)

    def set_session(self, user):
        try:
            assert ("_id" in user and "username" in user)
            session = {
                "_id": str(user["_id"]),
                "username": user["username"],
                "power": user["power"],
                "login_time": time.time()
            }
            self.session.set("current_user", session)
            return session
        except:
            return None

    def get_current_user(self):
        try:
            user = self.session.get("current_user")
            if not user and self.get_cookie("user_info"):
                scookie = self.get_secure_cookie("user_info")
                user = json.loads(scookie)
                if not self.set_session(user):
                    assert False
        except:
            user = None
        return user

    def get_ipaddress(self):
        if self.settings["intranet"]:
            return self.request.headers.get('X-Real-Ip')
        else:
            return self.request.remote_ip

    def pagenav(self, count, each, now, url):
        _ret = ''
        _pre = '<ul class="pagination pagination-sm">'
        _end = '</ul>'
        page = (int(count / each) + 1) if (count %
                                           each != 0) else (count / each)
        i = now - 5
        while (i <= now + 5) and (i <= page):
            if i > 0:
                if now == i:
                    _url = url % i
                    _ret += '<li class="active"><a href="javascript://">%d<span class="sr-only">(current)</span></a></li>' % (
                        i)
                else:
                    _url = url % i
                    _ret += '<li><a class="am-link-muted" href="%s">%d</a></li>' % (
                        _url, i)
            i += 1
        if now > 6:
            _url = url % 1
            _ret = u'<li><a href="%s">首页</a></li><li class="disabled"><a href="javascript://">...</a></li>%s' % (
                _url, _ret)
        if now + 5 < page:
            _url = url % page
            _ret = u'%s<li class="disabled"><a href="#">...</a></li><li><a href="%s">尾页</a></li>' % (
                _ret, _url)
        if page <= 1:
            _ret = u'<li class="active"><a href="javascript://">1<span class="sr-only">(current)</span></a></li>'
        _ret = _pre + _ret + _end
        return _ret

    @asynchronous
    def flush_session(self):
        def callback(user, error):
            if not user:
                return
            user["_id"] = str(user["_id"])
            user["login_time"] = self.current_user["login_time"]
            del user["password"]
            self.session.set("current_user", user)
            self.current_user = user
        self.db.member.find_one({
            "username": self.current_user["username"]
        }, callback=callback)


class AuthHandler(BaseHandler):

    def prepare(self):

        super(AuthHandler, self).prepare()

        self.power = "guest"
        power = {
            0: "user",
            20: "admin"
        }

        if self.current_user and self.current_user.get("power") in power:
            self.power = power[self.current_user["power"]]

        flush = self.get_cookie("flush_info", default=None)
        if self.current_user and not flush:
            self.flush_session()
            self.set_cookie("flush_info", "ok",
                            expires=time.time() + 60 * 10)


class UserBaseHandler(AuthHandler):

    def prepare(self):

        if not self.current_user:
            url = self.get_login_url()
            if "?" not in url:
                url += "?" + \
                    urlencode(dict(next=self.request.full_url()))
            self.redirect(url)

        super(UserBaseHandler, self).prepare()


class NotFoundHandler(BaseHandler):

    @not_need_login
    def prepare(self):
        BaseHandler.prepare(self)

    def get(self, *args, **kwargs):
        self.set_status(404)
        self.render("404.html")

    def post(self, *args, **kwargs):
        self.get(*args, **kwargs)
